package util
{
	import events.CheckTreeChangedEvent;
	
	import mx.collections.ArrayCollection;
	import mx.collections.ICollectionView;
	import mx.collections.IViewCursor;
	import mx.controls.Tree;
	import mx.controls.treeClasses.ITreeDataDescriptor;
	import mx.core.ClassFactory;
	import mx.events.ListEvent;
	import mx.events.TreeEvent;

	/**
	 * 三状态复选框树控件
	 */
	[Event(name="checkChanged", type="events.CheckTreeChangedEvent")]
	public class CheckTree extends Tree
	{
		private var _selectedField:String="selected";
		private var _expandField:String ="expand";
		//部分选中的填充色
		[Bindable]
		private var m_checkBoxBgColor:uint=0x009900;
		//取消选择是否收回子项
		[Bindable]
		private var m_checkBoxCloseItemsOnUnCheck:Boolean=true;
		//选择项时是否展开子项
		[Bindable]
		private var m_checkBoxOpenItemsOnCheck:Boolean=false;
		public function CheckTree()
		{
			super();
			doubleClickEnabled=true;
		}
		override protected function createChildren():void
		{
			var myFactory:ClassFactory=new ClassFactory(CheckTreeRenderer);
			this.itemRenderer=myFactory;
			super.createChildren();
			addEventListener(ListEvent.ITEM_DOUBLE_CLICK, onItemDClick);
			addEventListener(TreeEvent.ITEM_CLOSE,setDateExpend);
			addEventListener(TreeEvent.ITEM_OPEN,setDateExpend);
		}
		
		private function setDateExpend(event:TreeEvent):void
		{
			event.item[_expandField] = event.type == TreeEvent.ITEM_OPEN?true:false;
		}
		
		protected function checkboxSlecteChange(event:CheckTreeChangedEvent):void
		{
			dispatchEvent(event);
		}
		
		public function PropertyChange():void
		{
			dispatchEvent(new ListEvent(mx.events.ListEvent.CHANGE));
		}
		
		private function onItemDClick(e:ListEvent):void
		{
			OpenItems();
		}
		private function OpenItems():void
		{
			var isopen:Boolean = !this.isItemOpen(this.selectedItem);
			if (this.selectedIndex >= 0 && this.dataDescriptor.isBranch(this.selectedItem))
			{
				this.expandItem(this.selectedItem, isopen, true);
				this.selectedItem[_expandField] = isopen;
			}
		}
		/**
		 * 数据源中状态字段,0为不选，1为选择，2为半选
		 * @return 
		 * 
		 */		
		public function get selectedField():String
		{
			return _selectedField;
		}
		public function set selectedField(v:String):void
		{
			_selectedField=v;
			PropertyChange();
		}
		
		public function get expandField():String
		{
			return _expandField;
		}
		/**
		 * 父节点是否展开的字段
		 * @return 
		 * 
		 */
		public function set expandField(v:String):void
		{
			_expandField=v;
			PropertyChange();
		}
		
		/**
		 * 部分选中的填充色
		 * @return 
		 * 
		 */		
		[Bindable]
		public function get checkBoxBgColor():uint
		{
			return m_checkBoxBgColor;
		}
		public function set checkBoxBgColor(v:uint):void
		{
			m_checkBoxBgColor=v;
			PropertyChange();
		}
		
		/**
		 * 取消选择是否收回子项
		 * @return 
		 * 
		 */		
		[Bindable]
		public function get checkBoxCloseItemsOnUnCheck():Boolean
		{
			return m_checkBoxCloseItemsOnUnCheck;
		}
		public function set checkBoxCloseItemsOnUnCheck(v:Boolean):void
		{
			m_checkBoxCloseItemsOnUnCheck=v;
			PropertyChange();
		}
		
		
		/**
		 * 选择项时是否展开子项
		 * @return 
		 * 
		 */		
		[Bindable]
		public function get checkBoxOpenItemsOnCheck():Boolean
		{
			return m_checkBoxOpenItemsOnCheck;
		}
		public function set checkBoxOpenItemsOnCheck(v:Boolean):void
		{
			m_checkBoxOpenItemsOnCheck=v;
			PropertyChange();
		}
		
		/**
		 * 可以每次updatedisplay时自动更新状态，但是为了效率，手动更新此状态
		 * 
		 */
		public function updateExpandState():void
		{
			if(this.dataProvider!=null)
			{
				for each(var item:Object in this.dataProvider)
				{
					if(item[_expandField])
					{
						this.expandChildrenOf(item,true);
					}
				}
			}
		}
		/**
		 *更新父节点的三态显示 
		 * 
		 */		
		public function updateParentState():void
		{
			if(this.dataProvider!=null)
			{
				for each(var item:Object in this.dataProvider)
				{
					setState(item);
				}
			}
		}
		
		private function setState(parent:Object):void
		{
			var noChecks:int=0;
			var noCats:int=0;
			var noUnChecks:int=0;
			if (parent != null)
			{
				var treeData:ITreeDataDescriptor=this.dataDescriptor;
				
				var view :ICollectionView =treeData.getChildren(parent);
				if(view==null){
					return;
				}
				var cursor:IViewCursor=view.createCursor();
				while(!cursor.afterLast)
				{
					if (cursor.current[_selectedField] == 1)
						noChecks++;
					else if (cursor.current[_selectedField] == 0)
						noUnChecks++;
					else
						noCats++;
					cursor.moveNext();
				}
			}
			var oldValue:int=parent[_selectedField] as int;
			if ((noChecks > 0 && noUnChecks > 0) || noCats > 0)
				parent[_selectedField] = 2;
			else if (noChecks > 0)
				parent[_selectedField] = 1;
			else
				parent[_selectedField] = 0;
			
			this.dataProvider.itemUpdated(parent,_selectedField,oldValue,parent[_selectedField]);
		}
		
		private var _selectedItems:ArrayCollection = new ArrayCollection();
		public function GetSelectedItems():ArrayCollection
		{
			_selectedItems.removeAll();
			if(this.dataProvider !=null)
			{
				for(var i:int = 0 ; i < this.dataProvider.length ; i++ )
				{
					var childrenArray:Object = this.dataProvider[i].children;
					for (var c:int=0; c<childrenArray.length ;c++)
					{
						if(childrenArray[c].selected)
						{
							_selectedItems.addItem(childrenArray[c]);
						}
					}
				}
			}
			return _selectedItems;
		}
	}
}